A Powerful addition to BoxLang’s Java interoperability!
We’ve added more goodies to our BoxLang Java interop: method references and higher-order functions. CFML has never let you do these things, making Java Interop feel like a second-class citizen. But with BoxLang, we’re elevating Java integration to a new level.
Java Method References
In CFML, you can grab a reference to a UDF or closure, pass it around, and invoke it. BoxLang extends this to Java methods, both instance and static. Check this out:
boxlangCopy code
myInstance = new myClass();
myInstanceMethod = myInstance.myMethod;
myInstanceMethod();
And for static methods:
boxlangCopy code
myStaticUDF = src.test.java.TestCases.phase3.StaticTest::sayHello;
myStaticUDF();
Treating Java Methods as Objects
In BoxLang, Java methods (both instance and static) are objects you can pass around, invoke, and use in higher-order functions. When you reference a method on a Java class without parentheses, you get a special Function instance. This lets you treat the method like any other function.
Static Method Reference Example
Capture the static valueOf()
method from the Java String
class and invoke it:
boxlangCopy code
import java:java.lang.String;
javaStaticMethod = java.lang.String::valueOf;
result = javaStaticMethod("test"); // New string of "test"
Instance Method Reference Example
Capture the toUpperCase
method from a String
instance:
boxlangCopy code
javaInstanceMethod = "my string".toUpperCase;
result = javaInstanceMethod(); // "MY STRING"
Using Java Methods with Higher-Order Functions
BoxLang lets you use Java methods directly in place of UDFs or closures for higher-order functions. For example, sort an array in reverse order using Java’s Collections.reverseOrder().compare
method:
boxlangCopy code
import java.util.Collections;
[1, 7, 3, 99, 0].sort(Collections.reverseOrder().compare); // [99, 7, 3, 1, 0]
Limitations and Considerations
There are some limitations. Many Java methods can’t be used with CF/BL’s reduce
, each
, map
higher-order built-in functions (BIFs) because they strictly enforce the number of arguments. For example:
boxlangCopy code
import java:java.lang.Math;
[1, 2.4, 3.9, 4.5].map(Math::floor); // Error because floor only accepts a single arg!
The Math.floor()
method accepts a single argument, but arrayMap()
passes three arguments, causing an error.
Two-Way Compatibility with Java
BoxLang’s ability to pass closures into Java methods that accept functional interfaces or lambdas enhances two-way compatibility between Java and BoxLang. Check out this example of using a Java Stream
with a BoxLang lambda:
boxlangCopy code
fruits = ["apple", "banana", "cherry", "ananas", "elderberry"];
result = fruits.stream()
.filter(fruit -> fruit.startsWith("a"))
.toList();
Here, we convert a BoxLang array into a Java Stream
, use the Java filter()
method with a BoxLang lambda, and collect the results into a list.
Conclusion
With BoxLang’s new support for Java method references and higher-order functions, Java interop just got a whole lot cooler. This feature lets you write cleaner, more powerful code by leveraging Java’s capabilities within BoxLang’s modern syntax. Give it a try and see how it can boost your development experience!
Add Your Comment